package com.andy.wang.controller;

import com.alibaba.fastjson.JSONObject;
import com.andy.wang.pojo.Audit;
import com.andy.wang.pojo.Chitchat;
import com.andy.wang.service.AuditService;
import com.andy.wang.service.ChitchatService;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Component
@Slf4j
@ServerEndpoint("/webSocketSentTo/{username}/{userID}") //暴露的ws应用的路径
public class WebSocketSentTo implements ApplicationContextAware {

    /**
     * 当前在线客户端数量（线程安全的）
     */
    private static AtomicInteger onlineClientNumber = new AtomicInteger(0);

    /**
     * 当前在线客户端集合（线程安全的）：以键值对方式存储，key是连接的编号，value是连接的对象
     */
    private static Map<String, Session> onlineClientMap = new ConcurrentHashMap<>();


    // 获取Bean
    private static ApplicationContext applicationContext;


    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        WebSocketSentTo.applicationContext = applicationContext;
    }

    /**
     * 客户端与服务端连接成功
     *
     * @param session
     * @param username
     */
    @OnOpen
    public static void onOpen(Session session, @PathParam("username") String username, @PathParam("userID") String userID) {
        /*
            do something for onOpen
            与当前客户端连接成功时
         */
        onlineClientNumber.incrementAndGet();//在线数+1
        onlineClientMap.put(userID, session);//添加当前连接的session
        log.info("时间[{}]：与用户[{}]的连接成功，当前连接编号[{}]，当前连接总数[{}]",
                new Date().toLocaleString(),
                username,
                userID,
                onlineClientNumber);
    }

    /**
     * 客户端与服务端连接关闭
     *
     * @param session
     * @param username
     */
    @OnClose
    public static void onClose(Session session, @PathParam("username") String username, @PathParam("userID") int userID) {
        /*
            do something for onClose
            与当前客户端连接关闭时
         */
        onlineClientNumber.decrementAndGet();//在线数-1
        onlineClientMap.remove(userID);//移除当前连接的session
        log.info("时间[{}]：与用户[{}]的连接关闭，当前连接编号[{}]，当前连接总数[{}]",
                new Date().toLocaleString(),
                username,
                session.getId(),
                onlineClientNumber);
    }

    /**
     * 客户端与服务端连接异常
     *
     * @param error
     * @param session
     * @param username
     */
    @OnError
    public static void onError(Throwable error, Session session, @PathParam("username") String username) {
        /*
            do something for onError
            与当前客户端连接异常时
         */
        error.printStackTrace();
    }

    /**
     * 客户端向服务端发送消息
     *
     * @param message
     * @param sessionID
     * @throws IOException
     */
    @OnMessage
    public static void onMsg(Session session, String message, @PathParam("userID") String userID, @PathParam("sessionID") String sessionID, @PathParam("username") String username, @PathParam("type") String type, @PathParam("message") String chat, @PathParam("messageIMG") String imgURL, @PathParam("messageSVG") String svgURL) throws IOException {
        /*
            do something for onMessage
            收到来自当前客户端的消息时
         */
        log.info("时间[{}]：来自连接编号为[{}]的消息：[{}]",
                new Date().toLocaleString(),
                userID,
                message);

        String accpID = String.valueOf(JSONObject.parseObject(message).get("sessionID"));

        // 添加到聊天记录表
        ChitchatService chitchatService = getApplicationContext().getBean(ChitchatService.class);
        Chitchat chitchat = new Chitchat();
        chitchat.setUserID(Long.valueOf(String.valueOf(JSONObject.parseObject(message).get("userID"))));
        chitchat.setAcceptID(Long.valueOf(String.valueOf(JSONObject.parseObject(message).get("sessionID"))));
        if (JSONObject.parseObject(message).get("type").equals("1")) {
            chitchat.setMessage(String.valueOf(JSONObject.parseObject(message).get("message")));
        }else if (JSONObject.parseObject(message).get("type").equals("2")){
            chitchat.setMessageIMG(String.valueOf(JSONObject.parseObject(message).get("messageIMG")));

            // 添加聊天审核表
            AuditService auditService = getApplicationContext().getBean(AuditService.class);
            Audit audit = new Audit();
            audit.setUID(Long.valueOf(String.valueOf(JSONObject.parseObject(message).get("userID"))));
            audit.setAcceptID(Long.valueOf(String.valueOf(JSONObject.parseObject(message).get("sessionID"))));
            audit.setAuditIMG(String.valueOf(JSONObject.parseObject(message).get("messageIMG")));
            auditService.save(audit);
        } else if (JSONObject.parseObject(message).get("type").equals("3")) {
            chitchat.setMessageSVG(String.valueOf(JSONObject.parseObject(message).get("messageSVG")));

            // 添加聊天审核表
            AuditService auditService = getApplicationContext().getBean(AuditService.class);
            Audit audit = new Audit();
            audit.setUID(Long.valueOf(String.valueOf(JSONObject.parseObject(message).get("userID"))));
            audit.setAcceptID(Long.valueOf(String.valueOf(JSONObject.parseObject(message).get("sessionID"))));
            audit.setAuditSVG(String.valueOf(JSONObject.parseObject(message).get("messageSVG")));
            auditService.save(audit);
        }
        chitchatService.save(chitchat);

        sendMessageTo(accpID, message, userID);
    }

    //向所有客户端发送消息（广播）
    private static void sendAllMessage(String message) {
        Set<String> sessionIdSet = onlineClientMap.keySet(); //获得Map的Key的集合
        for (String sessionId : sessionIdSet) { //迭代Key集合
            Session session = onlineClientMap.get(sessionId); //根据Key得到value
            session.getAsyncRemote().sendText(message); //发送消息给客户端
        }
    }

    //给指定客户端发送消息，通过UserID和连接编号找到Session发送       // 连接编号添加的是用户ID
    private static void sendMessageTo(String sid, String obj, String uid) {


        Session session = onlineClientMap.get(uid);
        Session session2 = onlineClientMap.get(sid);
        try {
            if (session != null) {
                session.getAsyncRemote()
                        .sendText(obj);
            }
            if (session2 == null) {
                System.out.println("为空");
            } else {
                session2.getAsyncRemote()
                        .sendText(obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    //给指定客户端发送消息，通过UserID和连接编号找到Session发送       // 连接编号添加的是用户ID
    private static void roomMessage(String sid, String obj, String uid) {
        Session session = onlineClientMap.get(uid);
        Session session2 = onlineClientMap.get(sid);
        try {
            if (session != null) {
                session.getAsyncRemote()
                        .sendText(obj);
            }
            if (session2 != null) {
                session2.getAsyncRemote()
                        .sendText(obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }
}

